LoginSignup
15
16

More than 3 years have passed since last update.

多くの人(?)が通る道、保育園のアルバム委員の作業をGASで効率化した話

Last updated at Posted at 2020-12-11

背景

保育園の役員や謝恩会の委員、アルバム制作など、多くの人が経験することとと思います。
その中で、アルバム制作の写真集めを、GASを使って効率化した話を書きます。
エンジニアの仕事の効率化ではないことを最初に謝っておきます。ごめんなさい。
長女(9)の時に苦労して、長男(7)の時に効率化した話です。
GASのコードは、初めてGASを書いた状態なので燦々たる状態ですが、現状リファクタリングニーズがないのでこのまま供養します。

課題

子供達の保育園では、卒園アルバム制作が保護者のタスクとなっています。
例年、下記の内容でアルバム制作を進めています。
1. 業者選定
2. 分担(デザイン、撮影、データ)
3. 分担に分かれて作業
4. 納品
5. 配布

この中で、データ担当になり、写真データを集めて管理していた話です。
年にもよりますが、長女の時は、3000枚程度の写真を集めていました
何時間もかけて集めた写真をスキャンしていました、、、、

「各自、スキャンして送ってもらうのが良いが、メールで送ってもらったのを分類するのも大変そう、、、、どうせなら色々と自動でできないかしら。」
と思ったということで、長男の時には、いろんな条件で特定のドライブに移すものを作りました

使うもの

  • Googleメールアドレス
    • 画像メールの受け子
  • Googleドライブ
    • 画像の格納先
  • GoogleAppScript
    • いろいろ(後述)
  • GoogleSpreadsheet
    • いろいろの設定(後述)

GAS + SpreadSheetで行ったこと

  • GAS
    • 新着メールからの複数画像ファイルをSpreadSheetで指定したファイルへの移動
      • メールタイトルとフォルダを対応付け
      • ファイル→メールのトレーサビリティを確保するため、メールの日時をファイル名に付与(ファイルサイズが小さい等の返信をすることがあるので結構重要)
    • SpreadSheetで指定したファイル名への変更
      • 連番_〇〇ちゃん、というprefixを付けて、ソートできるようにした
新着メールからの複数画像ファイルをSpreadSheetで指定したファイルへの移動.gs

function gmailFileUploader(){

  //スプレッドシートを読み込む
  var spreadsheets = SpreadsheetApp.openById(SPREADSHEET_ID);
  var spreadsheet = spreadsheets.getSheetByName("フォルダ");

  //二次元配列に
  var data = spreadsheet.getRange(1,1,spreadsheet.getLastRow(),2).getValues();

  //タイトル名の配列と、ファイル名の配列にする
  folderArray = [];
  titleArray = [];
  for(var i = 0; i < data.length ; i++){
    titleArray.push(data[i][0]);
    folderArray.push(data[i][1]);
  }

  var Threads = GmailApp.getInboxThreads(); 
  for(var i=0;i<100;i++){ 
    if (!Threads[i]){return;}//メールがなければ抜ける
    var status = Threads[i].isUnread();
    var status_save = false;
    if(status==true){
      var subject = Threads[i].getMessages()[0].getSubject();
      for (var k = 0;k < titleArray.length;k++){
        if(data[k] != null && subject==titleArray[k]){//タイトルは0列目に
          for(var i_msg = 0; i_msg < Threads[i].getMessageCount(); i_msg++){
            var msg = Threads[i].getMessages()[i_msg];
            //既読だったら処理を飛ばして次のmsgへ
            if(msg.isUnread() == false){ continue; }
            var attachments = Threads[i].getMessages()[i_msg].getAttachments({includeInlineImages:true});
            var mailfrom = remove_dot(Threads[i].getMessages()[i_msg].getFrom()); 
            var folders = DriveApp.getFoldersByName(folderArray[k]);//フォルダは1列目に
            while(folders.hasNext()){
              var folder = folders.next();
              for(var j = 0;j<attachments.length;j++){
                var data = DriveApp.createFile(attachments[j]);
                //ファイル名に時間を入れる
                var new_file_name = Utilities.formatDate(msg.getDate(),"Asia/Tokyo","yyyyMMdd-HHmmss") + mailfrom + "_" + attachments[j].getName();
                data.setName(new_file_name);
                folder.addFile(data); 
                status_save=true;
              }
            }
            if(status_save){
              msg.markRead();//保存終了したら既読にする
            }
          }
          continue;//一致するタイトルが見つかったら次のループへ
        }
      }
    }
  }  
} 
//あとでメールアドレスから名前に変換するため、メールアドレスの@以前のドットを抜いた状態でファイル名につける
function remove_dot(mail_from){

  var reg = /<.*@.*>/g;
  var ret = "";

  if(mail_from.length > 0 && mail_from.match(reg) != null){
    ret = mail_from.match(reg)[0];
  }else{
    ret = mail_from; 
  }
  ret = ret.split("@")[0].replace(/@*/g,"").split('<').join('').split('.').join('');

  return ret;
}
SpreadSheetで指定したファイル名への変更.gs
function myFunction() {
  //スプレッドシートを読み込む
  var spreadsheets = SpreadsheetApp.openById(SPREADSHEET_ID);
  var spreadsheet = spreadsheets.getSheetByName("よみかえ");

  //エリアのサイズを取得
  var rowSize = spreadsheet.getDataRange().getHeight();
  var colSize = spreadsheet.getDataRange().getWidth();

  //jpegのみ収集
  var files = DriveApp.getFilesByType(MimeType.JPEG);

  var froms = spreadsheet.getRange(1, 1, rowSize, 1).getValues();
  var tos = spreadsheet.getRange(1, 2, rowSize, 1).getValues();
  //ファイル全てに対してループ

  var count = 0;
  while (files.hasNext()) {
    var file = files.next();

    for(var i = 1; i < rowSize ; i++){
      var from = froms[i]
      var name = tos[i]

      //ファイル名に指定文字列が含まれる、かつ、読み替え後文字列が存在すれば読み替える
      if(file.getName().indexOf(from) > 0 && name.length > 0){
        var fname = file.getName();
        file.setName(name + fname.replace(from,""));
        Logger.log(fname);
        count++;
        //読み替えたら次ループへ
        continue;
      }
    }
  }
  Logger.log(count);
}
  • SpreadSheet※個人情報満載なのでつけられません
    • タイトルによる格納先一覧
      • フォルダと、メールタイトルの対応付け
    • メールアドレスによる自動ファイル名付け一覧
      • 送信元メールアドレス(@以前のみ、ドットは削除)と、つけるprefixの対応付け

運用

  • 写真は、専用のメールアドレスにファイル添付で送ってもらうこととする
  • 「2歳児クラス」等の学年や、「5才遠足」等のイベントごとに、メールのタイトルと氏名等を含めたメールを作成するURL・QRコードを作成して一覧配布
    • 同時にLINEでも○歳は、タイトル「○才」で送ってね、という周知
    • (※ページの都合で、「5歳クラス」と「5歳遠足」というMECEじゃない分け方で困りそうな感じなのは私のせいじゃない)

振り返り等々

  • タイトル指定はなかなか難しい(半角全角の表記ゆれ等)
  • メールでデータを送る、が慣れていない人も
  • そもそもスキャンしたくない人も多くいた(そういう人は、スキャンしてまで送りたくない、となって枚数が減ってしまう。写真集めをタスクとしている身としては、目的を満たせないかなり大きな問題)
  • スキャン環境がない人の分は現物を受け取って実施した。以前と比べると現物受け取り枚数は減ったので、スキャンの負担をある程度分散できたように思う
  • この仕組みを使っても使わなくても、スキャン画像の荒さなどの問題がでる
  • 学年間違えて送ったりは目検で救済
  • 複数人から同じ写真が送られてくることがあり、皆が気に入って買っている写真があるのもあったが、人毎に分かれてしまうので、似た写真がわかるといいなと思った

感想

  • GASを当時初めて使ったけれど、便利だと思った、勉強になった!ここから私のGAS生活が始まった、、、!
  • 機械学習用の画像データを集めを複数人で行うときに便利かもと思ったり
  • 個人情報だらけのため、スプレッドシートが出せなくてすみません

今後

  • もう一人、次男(3)の分の仕事が残っています
  • この仕組みをまた使うかは分からないが、次回使うなら、画像サイズでの自動返信を入れたい、、、。「画像サイズが小さいので、担当まで現物を渡してください」のような感じで、、、、
  • GoogleFormの方が簡単かもしれないとちょっと思っています
  • LINEでのコミュニケーションを、Slackに出来たら、まだまだ色々と自動化できそうだな〜と思ったり。(進行スケジュールとか)
  • まあ細かい効率化はありますが、結局コミュニケーションを効率化することが一番、、、、
  • 4人目の予定はありません。たぶん。
15
16
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
16