GoogleAppsScript(GAS)を使用した業務効率化事例10選

GoogleAppsScript(GAS)を使用した業務効率化事例10選:

「どういうことが自動化できるのか」

普段の仕事から退屈な作業を取り除きたいなら
「自動化脳」をつくるべし

GoogleAppsScript(以下、GAS)はGmailのアカウントさえあれば

プログラミング学習に付随しがちな

環境設定

というものが特にいらないことや

ググればプログラマーじゃなくても

コピペで使えるようなプログラムが見つかったりするので

プログラマーに限らず様々な方々に使われているのかなと思います。

今回はそんなGASを使った簡単な(業務)効率化事例をいくつか共有できればと思います。

また、 「これ業務じゃないだろ」 というレベルの個人的なものも含んでおります。

できるだけ多くの事例を共有したいので

ひとつの愛嬌ということで許してください←


注意事項

*1. 今後も事例が増えれば追加していきますw

*2. 掲載してるプログラムの詳細な使い方は説明がめんどくさいので頑張って読み取ってください

*3. プログラムに間違いを発見した場合はこっそり編集リクエストを送ってくれると嬉しいですw


1. 名刺発注確認自動化

以下のような内容のGoogleフォームを作成し

フォームのリンクを含んだメールを月初に送信するようにしました。



Screen Shot 2018-10-19 at 19.57.48.png


GASのトリガーを使えば定期的にプログラムを実行することができるので、

トリガー実行日が月初の営業日であれば

メールを送信する、というプログラムです。

GASはGmailと簡単に連携できるので

メール送信自体はすごくシンプルに実装することができます。

var BK = SpreadsheetApp.getActiveSpreadsheet(), 
  SHEETS = BK.getSheets(), 
  TODAY = new Date(); 
 
/*** 
 * Hook google spread SHEET open action 
 */ 
function onOpen() { 
  SpreadsheetApp.getUi() 
    .createMenu('Custom Menu') 
    .addItem('Alert Mail', 'alertEmail') 
    .addItem('Remind mail', 'remindEmail') 
    .addToUi(); 
} 
 
/*** 
 * Send alert mail 
 */ 
function alertEmail() { 
  for (var i = 0, sheetLen = SHEETS.length; i < sheetLen; i++) { 
    var mail = SHEETS[i].getRange(1, 2, 9, 1).getValues(), 
      alertBusinessDays = String(mail[6][0]).split(','), 
      deadlineBusinessDays = String(mail[7][0]).split(','); 
    for (var j = 0, daysLen = alertBusinessDays.length; j < daysLen; j++) { 
      var alertDate = getBusinessDate(1, Number(alertBusinessDays[j])), 
        deadline = getBusinessDate(1, Number(deadlineBusinessDays[j])); 
      if (alertDate === TODAY.getDate()) { 
        var to = mail[0][0], 
          cc = mail[1][0], 
          bcc = mail[2][0], 
          subject = mail[3][0], 
          body = mail[4][0], 
          htmlBody = mail[5][0], 
          options = { 
            cc: cc, 
            bcc: bcc, 
            htmlBody: replacePlaceholder(htmlBody, deadline), 
            name: 'hogehoge', 
          }; 
        MailApp.sendEmail(to, replacePlaceholder(subject, deadline), replacePlaceholder(body, deadline), options); 
      } 
    } 
  } 
} 
 
/*** 
 * Send remind mail 
 */ 
function remindEmail() { 
  for (var i = 0, sheetLen = SHEETS.length; i < sheetLen; i++) { 
    var mail = SHEETS[i].getRange(9, 2, 4, 1).getValues(), 
      remindBusinessDays = mail[0][0], 
      remindMailTo = mail[1][0]; 
    if (remindBusinessDays && remindMailTo) { 
      var remindDate = getBusinessDate(1, remindBusinessDays); 
      if (remindDate === TODAY.getDate()) { 
        var subject = mail[2][0], 
          body = mail[3][0]; 
        MailApp.sendEmail(remindMailTo, subject, body); 
      } 
    } 
  } 
} 
 
/*** 
 * Send spreadsheet attachment 
 */ 
function sendResult() { 
  var nowDate = Utilities.formatDate(new Date(), 'JST', 'yyyyMMdd'); 
  var xlsxName = BK.getName() + "_" + nowDate + ".xlsx"; 
  var fetchOpt = { 
    "headers": {Authorization: "Bearer " + ScriptApp.getOAuthToken()}, 
    "muteHttpExceptions": true 
  }; 
  var key = BK.getId(); 
  var fetchUrl = "https://docs.google.com/feeds/download/spreadsheets/Export?key=" + key + "&exportFormat=xlsx"; 
  var attachmentFile = UrlFetchApp.fetch(fetchUrl, fetchOpt).getBlob().setName(xlsxName); 
  var recipient = "example@gmail.com"; 
  var subject = 'subject'; 
  var body = "body"; 
  var options = { 
    attachments: [attachmentFile] 
  }; 
  MailApp.sendEmail(recipient, subject, body, options); 
} 
 
/*** 
 * Replace placeholder like %%{string}%% 
 * @param value 
 * @param deadline 
 * @returns {XML|string} 
 */ 
function replacePlaceholder(value, deadline) { 
  return value.replace(/%%month%%/g, TODAY.getMonth() + 1).replace(/%%date%%/g, deadline); 
} 
 
/*** 
 * Get Japanese business date that after n days 
 * @param from 
 * @param afterNDays 
 * @returns {number} 
 */ 
function getBusinessDate(from, afterNDays) { 
  if (!afterNDays) { 
    throw new Error("Please set afterNDays properly"); 
  } 
  var calendar = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com'); 
  var fromDate = new Date(); 
  fromDate.setDate(from); 
  var i = 0; 
  var date = new Date(); 
  for (var dateCount = 0; dateCount !== afterNDays; i++) { 
    date.setDate(fromDate.getDate() + i); 
    var weekday = date.getDay(); 
    if (weekday !== 0 && weekday !== 6 && calendar.getEventsForDay(date, {max: 1}).length === 0) { 
      dateCount++; 
    } 
  } 
  return fromDate.getDate() + i - 1; 
} 


2. Googleカレンダー自動登録

いま働いてる会社には

週に1回、早く出社すれば早く帰れる

という制度があります。

その制度を利用するには

  1. 前日までにカレンダー登録する
  2. 上司をカレンダーの参加者に登録してメール通知を飛ばす
という手順が必要です。

そこで、

週明け営業日にその週の18時以降予定が入っていない日に自動でカレンダー設定して上司にメール通知するプログラムを作成しました。

// SlackApp Library Key => M3W5Ut3Q39AaIwLquryEPMwV62A3znfOO 
var SLACK_ACCESS_TOKEN = PropertiesService.getScriptProperties().getProperty('SLACK_ACCESS_TOKEN'), 
  HOLIDAY_CALENDAR = CalendarApp.getCalendarById("ja.japanese#holiday@group.v.calendar.google.com"), 
  SHUICHI_TEXT = '平井シューイチ', 
  GUEST_MAIL_ADDRESS = 'hoge@gmail.com'; 
 
function shuichi() { 
  // Execute at 9 o'clock on Monday 
  var calendar = CalendarApp.getDefaultCalendar(), 
    tuesday = new Date(), 
    friday = new Date(); 
  tuesday.addDays(1); 
  tuesday.setHours(18, 0, 0); 
  friday.addDays(4); 
  friday.setHours(23, 59, 59); 
  var weekEvents = calendar.getEvents(tuesday, friday); 
  var shuichiEvent = weekEvents.filter(function (e) { 
    if (e.getTitle().indexOf(SHUICHI_TEXT) !== -1) { 
      return e; 
    } 
  }); 
  if (shuichiEvent.length === 0) { 
    for (var i = 4; i > 0; i--) { 
      var from = new Date(), 
        to = new Date(); 
      from.addDays(i); 
      from.setHours(18, 0, 0); 
      to.addDays(i); 
      to.setHours(23, 59, 59); 
      var events = calendar.getEvents(from, to); 
      if (events.length === 0 && !isJapaneseHoliday(from)) { 
        var endTime = new Date(); 
        endTime.addDays(i); 
        endTime.setHours(19, 0, 0); 
        var option = { 
          guests: GUEST_MAIL_ADDRESS, 
          sendInvites: true 
        }; 
        calendar.createEvent(SHUICHI_TEXT, from, endTime, option); 
        var slackApp = SlackApp.create(SLACK_ACCESS_TOKEN); 
        var channelId = '[channel Id]'; 
        var options = { 
          as_user: true, 
          link_names: 1 
        }; 
        var message = '@here ' + from.getDate() + '日にシューイチ取得します。'; 
        slackApp.postMessage(channelId, message, options); 
        break; 
      } 
    } 
  } 
} 
 
function isJapaneseHoliday(targetDate) { 
  var year = targetDate.getYear(), 
    month = targetDate.getMonth(), 
    date = targetDate.getDate(); 
  var startDate = new Date(); 
  startDate.setFullYear(year, month - 1, date); 
  startDate.setHours(0, 0, 0, 0); 
  var endDate = new Date(); 
  endDate.setFullYear(year, month - 1, date); 
  endDate.setHours(23, 59, 59, 999); 
  var holidays = HOLIDAY_CALENDAR.getEvents(startDate, endDate); 
  return holidays.length !== 0; 
} 
 
Date.prototype.addDays = function (days) { 
  this.setDate(this.getDate() + parseInt(days)); 
  return this; 
}; 
こうすることで

設定し忘れて週末になっちゃって使えない

という事態を避けることができます。

圧倒的効率化です。

GASはGmailはもちろんGoogleカレンダーの登録も手軽に実装できるので良いですね。


3. 仮想通貨の自動積立購入

お気持ちはわかります。

だんだん業務効率化の方向からずれてきました。

ただ、まだ3つ目なので離脱するわけにはいかないという気持ちを逆手にとらせていただきました。

すいません><

これは仮想通貨取引所のAPIを使用して

毎日決まった時間に仮想通貨を決まった額購入するというプログラムです。

仮想通貨取引所で積立購入サービスの取り扱いをしているところが

自分の欲しい通貨を取り扱っていなかったため

取り扱い通貨のある取引所のAPIを使用して

積立購入プログラムを実装しました。

/** 
 * API Document => https://docs.bitbank.cc/#/ 
 */ 
var BK = SpreadsheetApp.getActiveSpreadsheet(), 
  SHEET = BK.getSheetByName('bitbank'), 
  DATA = SHEET.getRange(1, 2, 3, 1).getValues(), 
  API_KEY = DATA[0][0], 
  API_SECRET = DATA[1][0], 
  AMOUNT = DATA[2][0], 
  BITBANK = { 
    URL: { 
      PUBLIC: 'https://public.bitbank.cc', 
      PRIVATE: 'https://api.bitbank.cc/v1' 
    }, 
    PAIR: { 
      BTC_JPY: 'btc_jpy', 
      XRP_JPY: 'xrp_jpy', 
      LTC_BTC: 'ltc_btc', 
      ETH_BTC: 'eth_btc', 
      MONA_JPY: 'mona_jpy', 
      MONA_BTC: 'mona_btc', 
      BCC_JPY: 'bcc_jpy', 
      BCC_BTC: 'bcc_btc' 
    } 
  }; 
 
function getLastPrice(pair) { 
  var data = fetchJson(BITBANK.URL.PUBLIC + '/' + pair + '/ticker', 'GET', true).data; 
  // var high = data.high, 
  //   vol = data.vol, 
  //   last = data.last, 
  //   low = data.low, 
  //   sell = data.sell, 
  //   buy = data.buy, 
  //   timestamp = data.timestamp; 
  return data.last; 
} 
 
function order() { 
  [BITBANK.PAIR.XRP_JPY, BITBANK.PAIR.MONA_JPY].forEach(function (pair) { 
    var lastPrice = getLastPrice(pair), 
      body = { 
        pair: pair, 
        amount: AMOUNT / lastPrice, 
        //price: lastPrice, 
        side: 'buy', 
        type: 'market' 
      }, 
      result = fetchJson(BITBANK.URL.PRIVATE + '/user/spot/order', 'POST', false, body); 
    Logger.log(result); 
  }); 
} 
 
function fetchJson(url, method, isPublic, _body) { 
  var nonce = Date.now().toString(), 
    body = JSON.stringify(_body), 
    option = isPublic ? { 
      method: method, 
      contentType: 'application/json' 
    } : { 
      method: method, 
      payload: body, 
      headers: { 
        'ACCESS-KEY': API_KEY, 
        'ACCESS-NONCE': nonce, 
        'ACCESS-SIGNATURE': createSignature(url, nonce, body) 
      }, 
      contentType: 'application/json' 
    }; 
  return JSON.parse(UrlFetchApp.fetch(url, option)); 
} 
 
function createSignature(url, nonce, body) { 
  // ref: https://stackoverflow.com/questions/41232615/how-to-get-hex-value-from-computehmacsha256signature-method-of-google-apps-scrip 
  function toHex(signature) { 
    return signature.reduce(function (str, chr) { 
      chr = (chr < 0 ? chr + 256 : chr).toString(16); 
      return str + (chr.length === 1 ? '0' : '') + chr; 
    }, ''); 
  } 
 
  var text = (typeof body === 'undefined') ? 
    nonce + url : nonce + body; 
  Logger.log(text); 
  var signature = Utilities.computeHmacSha256Signature(text, API_SECRET); 
  return toHex(signature); 
} 
GASはHTTPリクエスト用のプログラムも用意してくれてるので

かなりお手軽にHTTPベースで外部サービスとの連携なんかもできてしまいます。


4. GitHubに毎日コミットするプログラム

これは主にプログラマ向けですが

GitHubのAPIを使用して

毎日コミット・プッシュするプログラムも書けます

var OWNER = 'yukihirai0505', 
  REPO = 'github-w-maker', 
  // GitHub access token from https://github.com/settings/tokens 
  GITHUB_ACCESS_TOKEN = PropertiesService.getScriptProperties().getProperty('GITHUB_ACCESS_TOKEN'), 
  GITHUB_BASE_API_URL = 'https://api.github.com', 
  REPOSITORY_CONTENTS_URL = GITHUB_BASE_API_URL + '/repos/' + OWNER + '/' + REPO + '/contents/' + '?access_token=' + GITHUB_ACCESS_TOKEN, 
  FILE_PATH_PLACEHOLDER = ':path', 
  FILE_URL = 'https://api.github.com/repos/' + OWNER + '/' + REPO + '/contents/' + FILE_PATH_PLACEHOLDER + '?access_token=' + GITHUB_ACCESS_TOKEN; 
 
// Create a file => https://developer.github.com/v3/repos/contents/#create-a-file 
function createFile() { 
  var message = 'create file randomly', 
    params = { 
      message: message, 
      committer: { 
        name: 'yukihirai0505', 
        email: 'hogehoge@gmail.com' 
      }, 
      content: Utilities.base64Encode(message) 
    }, 
    data = fetchJson(FILE_URL.replace(FILE_PATH_PLACEHOLDER, getRandomString()), 'PUT', params); 
  Logger.log(data); 
} 
 
function deleteRandomFile() { 
  var files = fetchJson(REPOSITORY_CONTENTS_URL, 'GET'), 
    file = files[0], 
    params = { 
      message: 'delete file randomly', 
      committer: { 
        name: 'yukihirai0505', 
        email: 'hogehoge@gmail.com' 
      }, 
      sha: file.sha 
    }, 
    data = fetchJson(FILE_URL.replace(FILE_PATH_PLACEHOLDER, file.name), 'DELETE', params); 
  Logger.log(data); 
} 
 
 
function fetchJson(url, method, params) { 
  var options = { 
    method: method, 
    payload: JSON.stringify(params) 
  }; 
  return JSON.parse(UrlFetchApp.fetch(url, options).getContentText()); 
} 
 
function getRandomString() { 
  return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); 
} 
GitHubに草を生やすためだけに毎日仕方なくプログラムを書く

というのは不毛です

自動化しましょう



スクリーンショット 2018-10-20 11.26.54.png


これによりスカウトサービス経由で

「GitHubをみましたが、すごくアクティブに活動されてますね」

みたいなメッセージがくることもあり

第一印象で好印象を抱かせることができます


5. クローラーの作成

GASにはHTTPリクエストのプログラムが用意されているということは

すでに書きました

これを利用すれば定期的なWEBサイトクロールにも使用することができます

注意点としてあまり対象サイトに負荷をかけないようにしましょう

クローラーを作成することで

定期的にWEBサイトを黙視してチェックしている項目などがあれば

それを自動化してスプレッドシートにチェック項目を毎日自動書き込みする

といったプログラムをつくれます

これは積み重ねていけばかなり大きな効率化につながります

また、クロールしたサイトの画面キャプチャをとってメールで送信することもできます。

いやー、便利ですね。


5. メルマガ機能

同じ内容のメールを複数人に一気に送りたいといった場合にも

GASが役立ちます。

メールアドレスを配列で管理して

それぞれのメールアドレスに対してメール送信することで

メルマガ機能のようなものもつくれます。

GASで書いたプログラムをWEBサービスとして公開することで

件名や内容を入力後

スプレッドシートで登録しているメールアドレスに一斉送信

といったことができます。

<html> 
<head> 
  <title>New Mail</title> 
</head> 
 
<body> 
<form> 
  <label for="subject">Subject: </label><br /> 
  <input type="text" name="subject" id="subject" value="%%name%%様" size="35"><br /><br /> 
  <label for="body">Message: </label><br /> 
  <textarea rows="30" cols="70" name="body" id="body">%%name%%様</textarea><br /> 
  <input type="button" onClick="formSubmit()" value="Submit" /> 
</form> 
</body> 
<script type="text/javascript"> 
  function formSubmit() { 
    google.script.run.newEmail(document.forms[0]); 
    google.script.host.close(); 
  } 
</script> 
 
</html> 
var BK = SpreadsheetApp.getActiveSpreadsheet(), 
  MAIL_LIST = BK.getSheetByName("MailList"); 
 
/*** 
 * Hook google spread SHEET open action 
 */ 
function onOpen() { 
  SpreadsheetApp.getUi() 
    .createMenu('CustomMenu') 
    .addItem('Create a new mail', 'openMailForm') 
    .addToUi(); 
} 
 
/*** 
 * Display mail form html 
 */ 
function openMailForm() { 
  var html = HtmlService.createHtmlOutputFromFile('index.html'); 
  SpreadsheetApp.getUi() 
    .showModalDialog(html, 'New Mail'); 
} 
 
/*** 
 * Get mail parameters 
 * @param form 
 */ 
function newEmail(form) { 
  var subject = form.subject; 
  var body = form.body; 
  sendMail(subject, body); 
} 
 
/*** 
 * Send mails 
 * @param subject 
 * @param body 
 */ 
function sendMail(subject, body) { 
  var lastRow = MAIL_LIST.getLastRow(); 
  var userList = MAIL_LIST.getRange(2, 1, lastRow, 2).getValues().filter(function (e) { 
    return e && e[0]; 
  }); 
  var to = MAIL_LIST.getRange(2, 4).getValue(); 
  var replyTo = MAIL_LIST.getRange(2, 5).getValue(); 
  var signature = MAIL_LIST.getRange(2, 3).getValue(); 
  for (var i = 0, len = userList.length; i < len; i++) { 
    var user = userList[i]; 
    var userMail = user[0]; 
    var userName = user[1]; 
    var options = { 
      replyTo: replyTo, 
      bcc: userMail 
    }; 
    MailApp.sendEmail(to, subject.replace("%%name%%", userName), body.replace("%%name%%", userName) + '\n\n\n' + signature, options); 
  } 
} 


6. シンプルなWEBサービスの作成

GASでつくったプログラムはWEBサービスとして無料で公開することができます。

Googleサービスと連携したサービスをサクッとつくってみたいときに

WEBページとして共有することで

非プログラマでも簡単に操作できるツールを作成することができます。


7. シンプルなAPIの作成

GASがWEBサービスとして公開することができることを

利用してシンプルなAPIを作成することもできます。

例えばWEBサービスとして公開した際のURLに対して

  • POSTリクエスト => カウントアップ
  • GETリクエスト => カウント数取得
のようなシンプルなAPIをサクッとサーバーレスで作れます。

もちろんパラメータをつけることもできるので、

頑張れば複雑なAPIを作成することも可能です。

サンプル

var COUNT_KEY = 'count'; 
 
function doPost(e) { 
  return createResponse(countUp()); 
} 
 
function doGet(e) { 
  return createResponse(getCount()); 
} 
 
function createResponse(count) { 
  var output = ContentService.createTextOutput(); 
  output.setMimeType(ContentService.MimeType.JSON); 
  output.setContent( 
    JSON.stringify({ 
      count: count 
    }) 
  ); 
  return output; 
} 
 
function getCount() { 
  return Number(PropertiesService.getScriptProperties().getProperty(COUNT_KEY)); 
} 
 
function countUp() { 
  var count = getCount() + 1; 
  PropertiesService.getScriptProperties().setProperty(COUNT_KEY, count); 
  return count; 
} 


8. Twitterの情報取得・自動ツイート

Twitterの情報を定期的に取得したり

決まった内容を定期的にツイートしたり

といったようなことができます

またTwitterに限らずAPIを公開しているサービスがあれば

同様のことが可能です。

仮想通貨の自動積立購入やGitHubの自動コミットも同じ要領で実装しています。

SlackのようなWebhook機能を備えているサービスも同じく可能です。

Googleのサービスとの連携だけでなく

他のサービスとの連携も簡単に行うことができますね。

例えば、10分ごとに特定キーワードでTwitter検索して

10分以内にツイートがあればSlackにそのツイートURLを送信する

みたいなプログラムも作成することができます。

あらゆるSNS(Youtube, Flickr, Facebook, Instagram etc)やコミュニケーションツール(Slack, Chatwork, Discord, Telegram etc)と連携することで

効率化が可能です。


9. 働いているフリをする

これは真似すると怒られるかもしれませんが

一応書いておきます。

真面目に働きたいという気持ちがあっても

人間は完璧ではありません

時にはサボりたくなることもあるでしょう。

そういったときに役立ちます。

Slackで自分にメンションがあった際に

そのメンション内容に ? が含まれている場合に

調べてみるので、少々お時間頂きます

と自動で返信するプログラムです。

もちろんパターンはいくつか用意しておくといいでしょう

また、よく自分にメンションでとんでくるメッセージ内容をざっとみてみると

ある程度いくつかのパターンにわけることができるので

それぞれに対応したメッセージを複数用意してレスポンスできるようにするのがベストです。

いや、ごめんなさい。

真面目に仕事するのがベストです←

他にも同じ要領で

きたメールに自動返信するようなプログラムを書いて

あたかも仕事してるかのように振舞うこともできます←

真似する際は自己責任でどうぞw


10. Twitterのフォロワー推移・YouTubeのチャンネル登録者推移記録

スプレッドシートに対象Twitterアカウントや

対象YouTubeチャンネルの日々のフォロワー数やチャンネル登録者数の増減を

記録していくプログラムを実装できます。

  • GASのトリガー(1日一回起動)
  • TwitterのAPI
  • YouTubeのAPI
といったものを駆使することで可能となります。


最後に

いまはまだ10選としてますが、

まだまだありますし

これからもまだまだ生まれてくると思うので

徐々に書き足していきます。

時間があればコードも掲載しようと思います。

コメント

このブログの人気の投稿

投稿時間:2021-06-17 22:08:45 RSSフィード2021-06-17 22:00 分まとめ(2089件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)