GASエディタ

【GAS】トリガーで毎日9時に自動処理 メール添付の請求書PDFを保存してチャットに通知⑫

前回のおさらい

前回はすべての処理が終わったときにメールを既読にする処理を書きました。

また、未読の請求書メールがなければif文を使って処理を抜けるようにしました。エラーになっちゃいますからね。

メールを既読にするためにメッセージオブジェクトのmarkReadメソッドを使いました。

const message = messages[0][0]
message.markRead()


未読の請求書メールが見当たらなければ処理を抜けるようにしました。

const searchedMail = gmail.search('from:株式会社 インボイス送信元 subject: 【請求書】送付のご案内 is:unread')
if (searchedMail.length === 0) return // 追加したコード


ここまででコード全体はこのようになっています。

const searchGmail = () => {
  const gmail = GmailApp
  const searchedMail = gmail.search('from:株式会社 インボイス送信元 subject: 【請求書】送付のご案内 is:unread')
  if (searchedMail.length === 0) return
  const messages = searchedMail.map(thread => {
    return thread.getMessages()
  })
  const message = messages[0][0]
  message.markRead()

  // 本文から税抜請求額と税込請求額を取得
  const messageBody = message.getPlainBody()
  const taxNotIncluded = messageBody.match(/税抜請求額.*$/m)[0]
  const taxIncluded = messageBody.match(/税込請求額.*$/m)[0]

  // 添付ファイルの取得とドライブへの保存
  const attachments = message.getAttachments()
  const drive = DriveApp
  const folder = drive.getFolderById('フォルダIDが入ります')
  const invoiceFile = folder.createFile(attachments[0])
  
  // チャット通知用メッセージの材料を集める
  const fromName = message.getFrom()
  const companyName = fromName.match(/"([^"]*)"/)[1]
  const invoiceUrl = invoiceFile.getDownloadUrl()
  
  // PDFからOCRでテキストを取り出す
  const document = Drive.Files.copy({ title: 'テスト' }, invoiceFile.getId(), { ocr: true })
  const documentApp = DocumentApp
  const documentFile = documentApp.openById(document.id)
  const documentBody = documentFile.getBody()
  const text = documentBody.getText()
  const invoiceDate = text.match(/(\d{4}年\d{1,2}月分)/)[1]
  invoiceFile.setName(`${invoiceDate} ${companyName} 請求書`)

  // 通知用のメッセージをつくる ※位置を上から移動
  const chatMessage = `${companyName}の${invoiceDate}請求書が届きました。\n${taxNotIncluded} ${taxIncluded}\n以下のURLからダウンロードしてください。\n${invoiceUrl}`
  
  // 不要なGoogleドキュメントファイルを削除する
  const removingFile = drive.getFileById(document.id)
  removingFile.setTrashed(true)

  sendChatwork(chatMessage)
  sendSlack(chatMessage)

  // スプレッドシートに転記する
  insertBillingAcount(invoiceDate, taxNotIncluded, taxIncluded)
}

// スプレッドシートに日付、税抜請求額、税込請求額を転記する関数
const insertBillingAcount = (invoiceDate, taxNotIncluded, taxIncluded) => {
  // 日付、税抜請求額、税込請求額を抜き出す
  // 日付は「分」を削除、税抜請求額、税込請求額は数字のみ抜き出す
  const date = invoiceDate.replace('分', '')
  const taxNotIncludedInt = taxNotIncluded.replace('税抜請求額 ', '').replace('円', '')
  const taxIncludedInt = taxIncluded.replace('税込請求額 ', '').replace('円', '')
  console.log(date, taxNotIncludedInt, taxIncludedInt)

  // 転記するセルを指定する
  const spreadSheetApp = SpreadsheetApp
  const spreadSheet = spreadSheetApp.openById('スプレッドシートIDが入ります')
  const sheet = spreadSheet.getSheetByName('請求額')
  const row = sheet.getLastRow() + 1
  const dateRange = sheet.getRange(row, 1) // 日付を記入するセルを指定
  const notIncludedRange = sheet.getRange(row, 2) // 税抜請求額を記入するセルを指定
  const includedRange = sheet.getRange(row, 3) // 税込請求額を記入するセルを指定

  // 日付を記入する
  dateRange.setValue(date)

  // 税抜請求額を記入する
  notIncludedRange.setValue(taxNotIncludedInt)

  // 税込請求額を記入する
  includedRange.setValue(taxIncludedInt)

}

// slackにメッセージを投稿する関数
const sendSlack = chatMessage => {
  const endpoint = 'https://slack.com/api/chat.postMessage'
  const token = 'APIトークンが入ります'
  const channel = 'チャネルIDが入ります'
  const text = chatMessage
  const payload = {
    token, channel, text
  }
  const options = {
    method: 'POST',
    payload,
  }
  const response = UrlFetchApp.fetch(endpoint, options)
  console.log(response.getResponseCode())
}

// チャットワークにメッセージを投稿する関数
const sendChatwork = chatMessage => {
  // endpointの定義
  const roomId = 'ルームID'
  const endpoint = `https://api.chatwork.com/v2/rooms/${roomId}/messages`

  // APIトークン
  const token = 'APIトークンが入ります'

  // リクエストボディ
  const message = chatMessage

  // リクエストボディにはメッセージのみを格納
  const payload = {
    body: message,
  }

  // ヘッダーにトークンをセット
  const headers = {
    'x-chatworktoken': token,
  }

  // optionsにheaderとpayload(リクエストボディ)をセット
  const options = {
    headers, payload
  }

  const response = UrlFetchApp.fetch(endpoint, options)
  console.log(response.getResponseCode())
}


今回はこのコードが毎日9時に自動的に実行されるようにトリガーを設定します。

トリガーの設定

トリガーとは

Google Apps Scriptにはトリガーという機能があります。

トリガーとは自動的にプログラムを実行する機能です。

いくつかの条件をもとに自動実行できます。

時間単位の自動実行

  • 分単位で実行 例)1分おきに実行
  • 時単位で実行 例)1時間おきに実行
  • 日単位で実行 例)毎日9時に実行
  • 週単位で実行 例)毎週月曜日9時に実行
  • 月単位で実行 例)毎月1日9時に実行

カレンダーの予定をもとに実行

バインドされているスプレッドシート、ドキュメント等のイベントによる自動実行

※バインドされている場合のみ可能

  • 起動されたら実行
  • 編集されたら実行
  • 変更されたら実行
  • フォーム送信されたら実行


今回は「毎日9時に実行」したいので時間単位の自動実行ですね。

トリガーの設定

GASエディタの左のメニューからトリガーをクリック

※マウスを目覚まし時計アイコンの上に持っていくとメニューがひらきます


右下の「トリガーを追加」をクリック

下のように設定します。

①実行する関数を選択

1つのトリガーで実行できる関数は一つのみです。このコードはsearchGmailを実行することで他の関数も含めてすべて実行するようになっていますのでsearchGmailを実行するようにします。

②イベントのソースを選択

「毎日9時」に実行するようにしたいので時間主導型にします。

③時間ベースのトリガーのタイプを選択

「毎日」なので日付ベースのタイマーにします。

④時刻を選択

「9時」なので午前9時〜10時にします。とはいえ、9時ぴったりに実行されるわけではなく、9時〜10時の良い頃合いの実行となります。


すべて設定が終わったら右下の保存ボタンをクリックします。


このようになっていればトリガー設定完了です。


というわけで現場からは以上です。

ちょうかんたん。


ここまで12回、メール添付の請求書PDFを保存してチャットに通知するコードを書いてきました。

これで経理に請求書を提出し忘れて怒られることはなくなりました。


Google Apps Scriptが威力を発揮するのは何らかのイベントが発生して、決まった処理を行う場合です。

今回であれば取引先から請求書メールが送られてくるイベントをもとにその後の処理を書いていきました。

この他にもいろいろ実現できます。


というわけで身の回りのいろんな定型業務を自動化していきましょう!

すると、いつの日かやることがなくなって逆に仕事をしたくなることでしょう。


ハイホー

Copied title and URL